package junior.util;

import junior.util.value.ValueUtils;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Iterator;
import org.springframework.util.Assert;

/**
 * @author WuBo
 * @CreateDate 2010-11-24
 * @version 1.0.1
 */
@SuppressWarnings("unchecked")
public abstract class ArrayUtils {
    
    public static <T> T[] ofCollection(Collection<T> collection) {
        if (collection == null) {
            return null;
        }
        return ofCollection(collection, getComponentType(collection));
    }
    
    public static <T> T[] ofCollection(Collection<?> collection, Class<T> componentType) {
        if (collection == null) {
            return null;
        }
        Object array = Array.newInstance(componentType, collection.size());
        int index = 0;
        for (Iterator<?> ite = collection.iterator(); ite.hasNext();) {
            Array.set(array, index++, ite.next());
        }
        return (T[]) array;
    }
    
    public static <T> Class<T> getComponentType(Collection<T> collection) {
        Assert.notNull(collection, "collection cannot be empty");
    
        if (!collection.isEmpty()) {
            return (Class<T>) collection.iterator().next().getClass();
        }
        
        Class<T> componentType = null;
        Type type = collection.getClass();
        if (type instanceof ParameterizedType) {
            ParameterizedType pt = (ParameterizedType) type;
            Type arg0 = pt.getActualTypeArguments()[0];
            if (arg0 instanceof Class) {
                componentType = (Class<T>) arg0;
            }
        }
        return componentType;
    }
    
	public static <T> boolean contains(T[] array, T t) {
		for (T item : array) {
			if (t.equals(item)) {
				return true;
			}
		}
		return false;
	}
	
	public static <T> T safeGet(T[] array, int idx) {
		if(array.length > idx) {
			return array[idx];
		}
		return null;
	}
	
	public static boolean isEmpty(Object[] objs){
		return objs == null || objs.length == 0;
	}
	
	public static <T> String join(T[] arrayObj, String split){
		return join(arrayObj, split, "");
	}

	public static <T> String join(T[] arrayObj, String split, String quote){
		return join(arrayObj, split, quote, quote);
	}

	public static <T> String join(T[] arrayObj, String split, String leftQuote, String rightQuote){
		if(arrayObj == null)return null;
		
		if(leftQuote == null) {
			leftQuote = "";
		}
		if(rightQuote == null) {
			rightQuote = "";
		}
		
		StringBuffer sb = new StringBuffer();
		for(int i=0; i<arrayObj.length; i++){
			if(i>0){
				sb.append(split);
			}
			sb.append(leftQuote);
			sb.append(arrayObj[i]);
			sb.append(rightQuote);
		}
		return sb.toString();
	}
	
	public static <T, R> R[] map(T[] array, Class<R> rsltArrayClass) {
		R[] rsltArray = (R[]) Array.newInstance(rsltArrayClass, array.length);
		for (int i=0; i<array.length; i++) {
			rsltArray[i] = ValueUtils.convert(array[i], rsltArrayClass);
		}
		return rsltArray;
	}

	/**
	 * 分隔处理一个大的数组
	 * @param array
	 * @param splitSize
	 * @param callback
	 * @throws Exception
	 */
	public static <T> void split(T[] array, int splitSize, ArraySplitCallback<T> callback) throws Exception {
		int count = array.length; // 总数
        int left = count; // 剩下的
        int idx = 0;
        int batch = 1;
        if (left <= 0) {
            return;
        }
        Class<?> componentType = array.getClass().getComponentType();
        
        while (left > 0) {
            int splitLength = splitSize;
            if (left < splitSize) splitLength = left;
    
            T[] splitValues = (T[]) Array.newInstance(componentType, splitLength);
            System.arraycopy(array, idx, splitValues, 0, splitLength);
            
            callback.onSplitValue((T[]) splitValues, batch ++);

            idx += splitLength;
            left = left - splitLength;
        }
	}
	
	public static interface ArraySplitCallback<T> {
		public void onSplitValue(T[] splitValues, int batch) throws Exception;
	}
	
}